
#include <ql/file_stream.h>

#include <ql/alloc.h>

struct QlFileStream
{
    const struct QlStreamVtbl * vtbl;

    bool                        auto_close;

    FILE *                      file;
};

static bool file_stream_seek(struct QlStream * stream, QlStreamInt offset)
{
    struct QlFileStream * fs = (struct QlFileStream *)stream;
    return (fseek(fs->file, (long)offset, SEEK_SET) == 0);
}

static QlStreamInt file_stream_read(struct QlStream * stream, char * data, QlStreamInt max_size)
{
    struct QlFileStream * fs = (struct QlFileStream *)stream;

    return fread(data, 1, max_size, fs->file);
}

static QlStreamInt file_stream_write(struct QlStream * stream, const char * data, QlStreamInt max_size)
{
    struct QlFileStream * fs = (struct QlFileStream *)stream;

    return fwrite(data, 1, max_size, fs->file);
}

static QlStreamInt file_stream_pos(struct QlStream * stream)
{
    struct QlFileStream * fs = (struct QlFileStream *)stream;
    long ret = ftell(fs->file);
    if (ret < 0)
    {
        return 0;
    }
    return (QlStreamInt)ret;
}

static void file_stream_free(struct QlStream * stream)
{
    struct QlFileStream * fs = (struct QlFileStream *)stream;

    if (fs->auto_close)
    {
        fclose(fs->file);
    }

    ql_free(fs);
}

static const struct QlStreamVtbl g_file_stream_vtbl =
{
    &file_stream_seek,
    &file_stream_read,
    &file_stream_write,
    &file_stream_pos,
    &file_stream_free,
};

struct QlStream * ql_create_file_stream(FILE * f, bool auto_close)
{
    struct QlFileStream * fs = ql_malloc(sizeof(struct QlFileStream));

    fs->vtbl = &g_file_stream_vtbl;
    fs->file = f;
    fs->auto_close = auto_close;

    return (struct QlStream *)fs;
}
